/*Yipeng Huang and Scott Rogowski*/
/*yh2315 smr2167*/

//Execute stage along with sequential logic.
module ExecuteStageWithRegisters (

					clk, reset, pause,

					//data inputs
					pc_plus_four, read_value_0, read_value_1,

					//instruction words
					sign_extended, instruction_20_16, instruction_15_11,
					
					//execute stage controls
					ALU_source, ALU_op, register_destination,
					
					//pass-through inputs
					mem_to_register_input, register_write_input, memory_read_input, memory_write_input, branch_input, jump_input, jump_address_input,
										
					//outputs
					branch_address, ALU_result, ALU_zero, register_write_address, data_memory_data,
					
					//pass-through outputs
					mem_to_register, register_write, memory_read, memory_write, branch, jump, jump_address
					
					);
					
	input clk, reset, pause;

	// data inputs
	input [31:0] pc_plus_four;
	input [31:0] read_value_0;
	input [31:0] read_value_1;

	// instruction words
	input [31:0] sign_extended;
	input [4:0] instruction_20_16;
	input [4:0] instruction_15_11;

	// execute stage controls
	input ALU_source;
	input [1:0] ALU_op;
	input register_destination;
	
	// pass-through inputs
	input mem_to_register_input;
	input register_write_input;
	input memory_read_input;
	input memory_write_input;
	input branch_input;
	input jump_input;
	input [31:0] jump_address_input;

	// outputs
	output [31:0] branch_address;
	output [31:0] ALU_result;
	output ALU_zero;
	output [4:0] register_write_address;
	output [31:0] data_memory_data;
	
	// pass-through outputs
	output mem_to_register;
	output register_write;
	output memory_read;
	output memory_write;
	output branch;
	output jump;
	output [31:0] jump_address;
	
	// wires
	wire [31:0] branch_address_mid;
	wire [31:0] ALU_result_mid;
	wire ALU_zero_mid;
	wire [4:0] register_write_address_mid; 

	// instantiate an execute stage
	ExecuteStage myExe (
			
			//inputs
			.pc_plus_four(pc_plus_four), .read_value_0(read_value_0), .read_value_1(read_value_1),
			.sign_extended(sign_extended), .instruction_20_16(instruction_20_16), .instruction_15_11(instruction_15_11),
			.ALU_source(ALU_source), .ALU_op(ALU_op), .register_destination(register_destination),
			// outputs
			.branch_address(branch_address_mid), .ALU_result(ALU_result_mid), .ALU_zero(ALU_zero_mid), .register_write_address(register_write_address_mid)
			);
	
	// pass-through control signals
	FF mem_to_register_dff	(.clk(clk), .reset(reset), .enable(!pause), .set(mem_to_register_input), .q(mem_to_register));
	FF register_write_dff	(.clk(clk), .reset(reset), .enable(!pause), .set(register_write_input), .q(register_write));
	FF memory_read_dff	(.clk(clk), .reset(reset), .enable(!pause), .set(memory_read_input), .q(memory_read));
	FF memory_write_dff	(.clk(clk), .reset(reset), .enable(!pause), .set(memory_write_input), .q(memory_write));
	FF branch_dff	(.clk(clk), .reset(reset), .enable(!pause), .set(branch_input), .q(branch));	
	FF jump_dff	(.clk(clk), .reset(reset), .enable(!pause), .set(jump_input), .q(jump));
	DelayRegisterFile jump_address_file (.clk(clk), .reset(reset), .pause(pause), .data(jump_address_input), .q(jump_address));

	// execute stage output buffers
	DelayRegisterFile branch_address_file (.clk(clk), .reset(reset), .pause(pause), .data(branch_address_mid), .q(branch_address));
	DelayRegisterFile ALU_result_file (.clk(clk), .reset(reset), .pause(pause), .data(ALU_result_mid), .q(ALU_result));
	DelayRegisterFile data_memory_data_file (.clk(clk), .reset(reset), .pause(pause), .data(read_value_1), .q(data_memory_data));
	FF ALU_zero_dff (.clk(clk), .reset(reset), .enable(!pause), .set(ALU_zero_mid), .q(ALU_zero));
	DelayRegisterFile #(5) register_write_address_file (.clk(clk), .reset(reset), .pause(pause), .data(register_write_address_mid), .q(register_write_address));

	endmodule